package mapper

import (
	"bytes"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"go-zero-project/services/user/rpc/internal/mapper/bo"
	"go-zero-project/services/user/rpc/internal/mapper/do"
	"go-zero-project/services/user/rpc/internal/mapper/entity"
	"gorm.io/gorm"
)

const deptSqlColumn = "dept_id,parent_id,name,order_num,del_flag"

type DeptMapper struct {
}

func NewDeptMapper() *DeptMapper {
	return &DeptMapper{}
}

func (mapper *DeptMapper) SelectOne(db *gorm.DB, bo bo.SysDeptBO) (entity.SysDeptEntity, error) {
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	whereSql := mapper.getAllWhereSql(bo)
	var user entity.SysDeptEntity
	tx = tx.Select(deptSqlColumn).Where(whereSql.String()).First(&user)
	return user, tx.Error
}

func (mapper *DeptMapper) SelectCount(db *gorm.DB, bo bo.SysDeptBO) (int64, error) {
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	whereSql := mapper.getAllWhereSql(bo)
	var total int64
	userEntity := entity.SysDeptEntity{}
	tx = tx.Select(deptSqlColumn).Table(userEntity.TableName()).Where(whereSql.String()).Count(&total)
	return total, tx.Error
}

func (mapper *DeptMapper) SelectList(db *gorm.DB, bo bo.SysDeptBO) ([]entity.SysDeptEntity, error) {
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	whereSql := mapper.getAllWhereSql(bo)
	logx.Infof(whereSql.String())
	whereSql.WriteString(" order by order_num desc")
	var retList []entity.SysDeptEntity
	if bo.PageSize > 0 {
		// 查询语句
		tx = tx.Select(deptSqlColumn).Where(whereSql.String()).Offset(bo.StartIndex).Limit(bo.PageSize).Find(&retList)
	} else {
		// 查询语句
		tx = tx.Select(deptSqlColumn).Where(whereSql.String()).Find(&retList)
	}
	return retList, tx.Error
}

func (mapper *DeptMapper) getAllWhereSql(roleBO bo.SysDeptBO) bytes.Buffer {
	var whereSql bytes.Buffer
	whereSql.WriteString(defaultWhere)
	if roleBO.DeptId > 0 {
		whereSql.WriteString(fmt.Sprintf(" and dept_id =%d", roleBO.DeptId))
	}
	if !roleBO.NonParentId {
		whereSql.WriteString(fmt.Sprintf(" and parent_id =%d", roleBO.ParentId))
	}
	if len(roleBO.Name) > 0 || roleBO.Name != "" {
		whereSql.WriteString(fmt.Sprintf(" and name ='%s'", roleBO.Name))
	}
	if len(roleBO.NameLike) > 0 || roleBO.NameLike != "" {
		whereSql.WriteString(fmt.Sprintf(" name  like concat ('%s','%s','%s')",
			"%", roleBO.NameLike, "%"))
	}
	if roleBO.OrderNum > 0 {
		whereSql.WriteString(fmt.Sprintf(" and order_num =%d", roleBO.OrderNum))
	}
	if roleBO.HasDelFlag {
		whereSql.WriteString(fmt.Sprintf(" and del_flag =%d", roleBO.DelFlag))
	}
	if roleBO.StartTime != nil {
		whereSql.WriteString(fmt.Sprintf(" and create_time >='%s'", roleBO.StartTime))
	}
	if roleBO.EndTime != nil {
		whereSql.WriteString(fmt.Sprintf(" and update_tim <'%s'", roleBO.EndTime))
	}
	return whereSql
}

func (mapper *DeptMapper) SelectDeptByUserId(db *gorm.DB, userId int64) (entity.SysDeptEntity, error) {
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	var deptEntity entity.SysDeptEntity
	userEntity := entity.SysUserEntity{}
	tx = tx.Select("t1.dept_id,t1.parent_id,t1.name").
		Table(userEntity.TableName()).Joins("left join sys_dept t1 on sys_user.dept_id=t1.dept_id").
		Where("sys_user.user_id", userId).First(&deptEntity)
	return deptEntity, tx.Error
}

func (mapper *DeptMapper) SelectSubCount(db *gorm.DB, deptIdArr []int64) ([]do.SubCountDO, error) {
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	//select parent_id,count(*) from sys_dept where parent_id != 0 GROUP BY parent_id;
	deptEntity := entity.SysDeptEntity{}
	var subCountArr []do.SubCountDO
	tx = tx.Table(deptEntity.TableName()).Select("parent_id as dept_id,count(*) as count").
		Where("parent_id in ?", deptIdArr).Group("parent_id").Find(&subCountArr)
	return subCountArr, tx.Error
}

func (mapper *DeptMapper) SelectOneForParentName(db *gorm.DB, deptId int64) (do.SysDeptDO, error) {
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	var deptDo do.SysDeptDO
	tx = tx.Select("s.dept_id,s.parent_id,s.name,s.order_num,s.del_flag,p.name as parent_name").
		Table("sys_dept s").Joins("left join sys_dept p on s.parent_id=p.dept_id").
		Where("s.dept_id =? and s.del_flag = 0", deptId).First(&deptDo)
	return deptDo, tx.Error
}

func (mapper *DeptMapper) DeleteDept(tx *gorm.DB, id int64) error {
	deptEntity := entity.SysDeptEntity{
		DeptId: id, DelFlag: -1,
	}
	tx = tx.Where("dept_id=?", id).UpdateColumns(deptEntity)
	return tx.Error

}

func (mapper *DeptMapper) Save(db *gorm.DB, deptEntity *entity.SysDeptEntity) (err error) {
	tx := db.Create(deptEntity)
	return tx.Error
}

func (mapper *DeptMapper) Update(db *gorm.DB, deptEntity entity.SysDeptEntity) error {
	tx := db.Where("dept_id = ?", deptEntity.DeptId).Omit("dept_id").
		UpdateColumns(deptEntity)
	return tx.Error
}
